<?php
// 应用公共文件

use app\admin\exception\AdminServiceException;
use app\admin\service\AdminAuthService;
use app\common\service\SettingService;
use support\Response;



if (!function_exists('setting')) {
    /**
     * 获取设置内容
     * @param string|array $name
     */
    function setting($name = '')
    {
        return (new SettingService())->getSetting($name);
    }
}

if (!function_exists('get_database_setting')) {
    /**
     * 获取数据库配置
     * @param $name
     * @return array|mixed|null
     */
    function get_database_setting($name)
    {
        return (new SettingService())->getDatabaseSetting($name);
    }
}


if (!function_exists('htmlentities_view')) {
    /**
     * 封装默认的 htmlentities 函数，避免在php8.1环境中view传入null报错
     * @param mixed $string
     * @return string
     */
    function htmlentities_view($string): string
    {
        return htmlentities((string)$string);
    }
}

if (!function_exists('parse_name')) {
    /**
     * 字符串命名风格转换
     * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
     * @param string $name 字符串
     * @param int $type 转换类型
     * @param bool $up_first 首字母是否大写（驼峰规则）
     * @return string
     */
    function parse_name(string $name, int $type = 0, bool $up_first = true): string
    {
        if ($type) {
            $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $name);

            return $up_first ? ucfirst($name) : lcfirst($name);
        }

        return strtolower(trim(preg_replace('/[A-Z]/', '_\\0', $name), '_'));
    }
}

if (!function_exists('get_request_url')) {
    /**
     * 获取请求的url，格式为：app/controller/action
     * @return string
     */
    function get_request_url(): string
    {
        $app        = request()->app;
        $controller = request()->controller;
        $action     = request()->action;

        $pos1 = strrpos($controller, '\\');
        $pos2 = strrpos($controller, 'Controller');

        if ($pos1 !== false && $pos2 !== 0) {
            $controller = substr($controller, $pos1 + 1, $pos2 - $pos1 - 1);
        }

        return $app . '/' . $controller . '/' . $action;
    }
}

if (!function_exists('admin_error')) {
    /**
     * 后台操作失败返回消息
     * @param string $msg
     * @param string $url
     * @param array $data
     * @return Response
     */
    function admin_error(string $msg = '操作失败', string $url = URL_CURRENT, array $data = []): Response
    {
        $data = [
            'msg'  => $msg,
            'code' => ADMIN_ERROR_CODE,
            'data' => empty($data) ? (object)$data : $data,
            'url'  => $url,
        ];

        return json($data);
    }
}


if (!function_exists('admin_success')) {
    /**
     * 后台操作成功返回消息
     * @param string $msg
     * @param array $data
     * @param string $url
     * @return Response
     */
    function admin_success(string $msg = '操作成功', array $data = [], string $url = URL_CURRENT): Response
    {
        $data = [
            'msg'  => $msg,
            'code' => ADMIN_SUCCESS_CODE,
            'data' => empty($data) ? (object)$data : $data,
            'url'  => $url,
        ];

        return json($data);
    }
}

if (!function_exists('token')) {
    /**
     * 生成token
     * @param string $name
     * @return string
     */
    function token(string $name = '__token__'): string
    {
        $token = sha1($name . microtime() . uniqid($name, true));

        session([$name => $token]);

        return $token;
    }
}

if (!function_exists('token_field')) {
    /**
     * 生成令牌隐藏表单
     * @param string $name 令牌名称
     * @return string
     * @throws Exception
     */
    function token_field(string $name = '__token__'): string
    {
        $token = token($name);

        return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
    }
}

if (!function_exists('captcha_check')) {
    /**
     * 检查验证码
     * @param $captcha
     * @return bool
     */
    function captcha_check($captcha): bool
    {
        return strtolower($captcha) === (request())->session()->get('captcha');
    }
}

if (!function_exists('url')) {

    /**
     * 生成url
     * @param string $url
     * @param array $vars 变量
     * @param false $domain 域名
     * @return string
     */
    function url(string $url = '', array $vars = [], bool $domain = false): string
    {

        // 如果不是/开头
        if (strpos($url, '/') !== 0) {
            $app = request()->app;
            if ($app !== null) {
                // 如果有/分割
                if (strpos($url, '/') !== false) {
                    $arr  = explode('/', $url);
                    $size = count($arr);
                    if ($size === 3) {
                        if ($arr[0] === $app) {
                            $url = '/' . $url;
                        }
                    } else if ($size === 2) {
                        $url = '/' . $app . '/' . $url;
                    }

                } else {
                    // 如果只有方法，自动补全当前应用和controller
                    $request_url = get_request_url();
                    $request_arr = explode('/', $request_url);
                    $url         = '/' . $app . '/' . $request_arr[1] . '/' . $url;
                }
            }
        }

        // 设置query参数
        if (!empty($vars)) {
            $url   .= '?';
            $query = '';
            foreach ($vars as $key => $val) {
                $query .= empty($query) ? $key . '=' . $val : '&' . $key . '=' . $val;
            }
            $url .= $query;
        }

        // 设置域名
        if ($domain && strpos($url, '://') === false) {
            $host = (request())->host();
            if (strpos($url, '/') !== 0) {
                $url = '/' . $url;
            }
            // 组装域名,TODO::这里需要判断https和http，后续调整
            $url = 'http://' . $host . $url;
        }

        if (strpos($url, '/') !== 0 && strpos($url, 'http:') === false) {
            $url = '/' . $url;
        }

        return $url;
    }
}


if (!function_exists('api_unauthorized')) {
    /**
     * 未认证（未登录）
     * @param string $msg
     * @param mixed $data
     * @param int $code
     * @return Response
     */
    function api_unauthorized(string $msg = 'unauthorized', $data = [], int $code = 401): Response
    {
        return api_result($msg, $data, $code);
    }
}

if (!function_exists('api_forbidden')) {
    /**
     * 无权限
     * @param string $msg
     * @param mixed $data
     * @param int $code
     * @return Response
     */
    function api_forbidden(string $msg = 'forbidden', $data = [], int $code = 403): Response
    {
        return api_result($msg, $data, $code);
    }
}


if (!function_exists('api_success')) {
    /**
     * 操作成功
     * @param mixed $data
     * @param string $msg
     * @param int $code
     * @return Response
     */
    function api_success(array $data = [], string $msg = 'success', int $code = 200): Response
    {
        return api_result($msg, $data, $code);
    }
}

if (!function_exists('api_error')) {
    /**
     * 操作失败
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_error(string $msg = 'fail', array $data = [], int $code = 500): Response
    {
        return api_result($msg, $data, $code);
    }
}

if (!function_exists('api_result')) {
    /**
     * 返回json结果
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_result(string $msg = 'fail', array $data = [], int $code = 500): Response
    {
        $header = [
            'Content-Type' => 'application/json',
            'Server'       => config('app.app_name'),
        ];
        // http code是否同步业务code
        $http_code = config('api.response')['http_code_sync'] ? $code : 200;

        $result = [
            'code' => $code,
            'msg'  => $msg,
            'data' => empty($data) ? (object)$data : $data,
        ];
        try {
            $body = json_encode($result, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
        } catch (JsonException $e) {
            $body = '{"code":500,"msg":"' . $e->getMessage() . '","data":{}}';
        }

        return new Response($http_code, $header, $body);
    }
}


if (!function_exists('api_service_unavailable')) {
    /**
     * 系统维护中
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_service_unavailable(string $msg = 'service unavailable', array $data = [], int $code = 503): Response
    {
        return api_result($msg, $data, $code);
    }
}


if (!function_exists('api_error_client')) {
    /**
     * 客户端错误 例如提交表单的时候验证不通过，是因为客户填写端错误引起的
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_error_client(string $msg = 'client error', array $data = [], int $code = 400): Response
    {
        return api_result($msg, $data, $code);
    }
}

if (!function_exists('api_error_server')) {
    /**
     * 服务端错误
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_error_server(string $msg = 'server error', array $data = [], int $code = 500): Response
    {
        return api_result($msg, $data, $code);
    }
}

if (!function_exists('api_error_404')) {
    /**
     * 资源或接口不存在
     * @param string $msg
     * @param array $data
     * @param int $code
     * @return Response
     */
    function api_error_404(string $msg = '404 not found', array $data = [], int $code = 404): Response
    {
        return api_result($msg, $data, $code);
    }
}


if (!function_exists('index_success')) {

    function index_success($msg = '操作成功', $url = URL_BACK, $data = '', $wait = 0, array $header = []): Response
    {
        return index_result(200, $msg, $data, $url, $wait, $header);
    }
}


if (!function_exists('index_error')) {
    function index_error($msg = '操作失败', $url = URL_CURRENT, $data = '', $wait = 0, array $header = []): Response
    {
        return index_result(500, $msg, $data, $url, $wait, $header);
    }
}

if (!function_exists('index_result')) {
    function index_result($code = 200, $msg = 'unknown', $data = '', $url = null, $wait = 3, array $header = []): Response
    {
        $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : url($url);
        if ((request())->method() === 'POST' || (request())->isAjax()) {
            $result = [
                'code' => $code,
                'msg'  => $msg,
                'data' => $data,
                'url'  => $url,
                'wait' => $wait,
            ];

            $server = [
                'Content-Type' => 'application/json',
                'Server'       => config('app.app_name'),
            ];

            $header = array_merge($header, $server);

            try {
                $body = json_encode($result, JSON_THROW_ON_ERROR);
            } catch (JsonException $e) {
                $body = '{"code":500,"msg":"' . $e->getMessage() . '","data":{}}';
            }

            return new Response(200, $header, $body);
        }

        if ($url === null) {
            $url = (request())->header('HTTP_REFERER') ?? url('index/index/index');
        }

        return redirect($url);
    }
}


if (!function_exists('view_check_auth')) {
    /**
     * 前端检查权限，，主要用在元素的显示上，使用方法，在需要判断权限的元素上添加class"viewCheckAuth"和data-auth属性
     * 例如：  data-auth="{:view_check_auth('question_library/add')}"，
     * 当有权限的时候会自动显示该元素，没有权限的时候不会显示该元素
     *  url形式参考：user/edit，admin/user/edit，前缀"admin/"可以去掉
     * @param $url
     * @return string
     */
    function view_check_auth($url): string
    {
        try {
            return (new AdminAuthService())->viewCheckAuth($url);
        } catch (AdminServiceException $e) {
            return '0';
        }
    }
}
